﻿using System;
using System.Timers;
using System.Windows;

namespace Com.Lancetinc.Evs.Helpers
{
    public class UserMouseMoveDetector : IDisposable
    {
        private readonly UIElement _element;
        private bool _isStopping = false;
        private bool _detectStarted = false;
        public bool DetectStarted => _detectStarted;
        public event EventHandler MouseStopped;
        public event EventHandler MouseMoved;

        public TimeSpan DetectThreshold { get; set; } = TimeSpan.FromSeconds(1.5);
        private readonly Action _waitForStopWrapper;
        public UserMouseMoveDetector(UIElement element)
        {
            _element = element;
            _waitForStopWrapper = WpfHelper.Debounce(WaitForStop, 500);
        }

        public void Start()
        {
            if (_detectStarted)
                return;
            _detectStarted = true;
            _element.MouseMove += _element_MouseMove;
        }

        public void Stop()
        {
            _detectStarted = false;
            _mouseStopTimer?.Stop();
            _element.MouseMove -= _element_MouseMove;
        }

        private void _element_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (!_detectStarted) return;

            if (_isStopping)
            {
                _isStopping = false;
                MouseMoved?.Invoke(this, EventArgs.Empty);
            }

            _waitForStopWrapper();
        }

        private Timer _mouseStopTimer;
        private void WaitForStop()
        {
            _mouseStopTimer?.Stop();
            _mouseStopTimer = new Timer(DetectThreshold.TotalMilliseconds);
            _mouseStopTimer.Elapsed += _mouseStopTimer_Elapsed;
            _mouseStopTimer.AutoReset = false;
            _mouseStopTimer.Start();
        }

        private void _mouseStopTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _isStopping = true;
            if (!_detectStarted) return;

            MouseStopped?.Invoke(this, EventArgs.Empty);
        }

        public void Dispose()
        {
            Stop();
        }
    }
}